import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Map.Entry;
import java.util.AbstractMap.SimpleEntry;
import algorithms.GPAlgorithm;
import algorithms.Selection.SelectionFactory.SelectionMode;

/**
 * @throws IOException
 */
public class Main {

	/**
	 * The main method executes the GP using the training data from the input file 
	 * and writes the solution to an output file
	 * 
	 * @throws IOException 
	 **/
	public static void main(String[] args) throws IOException {

		// read input
		List<Entry<Double,Double>> data = readFile();

		// run GP with rank based selection mode
		GPAlgorithm gp = new GPAlgorithm(data, SelectionMode.RankBasedSelection);
		gp.Run();

		// write result
		writeResult(gp.GetSolution().toString());
		//System.out.println(gp.GetSolution().toString());
	}


	/**
	 * Reads the input file line by line, parse it and returns a list holding
	 * all the entries from the file
	 * 
	 * @return the list holding all the entries from the file
	 * @throws IOException
	 */
	public static List<Entry<Double,Double>> readFile() throws IOException {

		BufferedReader input = null; // used for reading input file content
		String line = null; // represent a single line content
		List<Entry<Double,Double>> data = new ArrayList<Entry<Double,Double>>();

		try {

			// reading input file
			FileReader reader = new FileReader("data.txt");
			input =  new BufferedReader(reader);

			// read header line
			line = input.readLine();

			int lineNum = 1;
			while ((line = input.readLine()) != null) {

				lineNum ++;

				// read arguments
				String[] arguments = line.split(",");
				if (arguments.length < 2)
					throw new IllegalArgumentException("Argument missing, line #" + lineNum);

				// add to data list
				Double x = Double.parseDouble(arguments[0]);
				Double y = Double.parseDouble(arguments[1]);
				Entry<Double, Double> element = new SimpleEntry<Double, Double>(x,y); 
				data.add(element);
			}

		} catch(Exception e) {
			e.printStackTrace();
		} finally {
			if (input != null) input.close();
		}

		return data;
	}

	/**
	 * Write the output into a file 'equation.txt'
	 * 
	 * @param output - the output string
	 * @throws IOException
	 */
	public static void writeResult(String output) throws IOException {
		BufferedWriter out = null;
		try {
			FileWriter writer = new FileWriter("equation.txt");
			out = new BufferedWriter(writer);
			out.write(output);
		} catch (Exception e) {
			e.getStackTrace();
		} finally {
			if (out != null) out.close();
		}
	}

}
